package com.yunji.cabinet.business;

import com.yunji.base.cache.BaseCache;
import com.yunji.base.domain.BelongDO;
import com.yunji.base.dto.AgentDTO;
import com.yunji.base.event.GuavaEventBus;
import com.yunji.base.service.AgentService;
import com.yunji.base.service.SiteService;
import com.yunji.base.service.StaffService;
import com.yunji.cabinet.bo.*;
import com.yunji.cabinet.cache.CabinetCache;
import com.yunji.cabinet.consumer.CabinetConsumer;
import com.yunji.cabinet.context.calculate.CabinetCalculate;
import com.yunji.cabinet.context.convert.CabinetConvert;
import com.yunji.cabinet.context.validate.CabinetValidate;
import com.yunji.cabinet.device.ContainerTypeEnum;
import com.yunji.cabinet.device.DeviceCommandEngine;
import com.yunji.cabinet.device.DeviceCommandEnum;
import com.yunji.cabinet.device.DeviceEventEnum;
import com.yunji.cabinet.domain.*;
import com.yunji.cabinet.dto.CabinetBindDTO;
import com.yunji.cabinet.dto.CabinetCargoDTO;
import com.yunji.cabinet.dto.CabinetDTO;
import com.yunji.cabinet.dto.device.CabinetCargoInfoDTO;
import com.yunji.cabinet.dto.device.DeviceCommandDTO;
import com.yunji.cabinet.dto.device.DeviceEventDTO;
import com.yunji.cabinet.engine.generate.CabinetDataCodeGenerate;
import com.yunji.cabinet.enums.*;
import com.yunji.cabinet.service.*;
import com.yunji.cabinet.service.impl.DeviceService;
import com.yunji.cabinet.service.impl.FillCargoInfoService;
import com.yunji.cabinet.service.impl.MaintainService;
import com.yunji.cabinet.vo.CabinetCellVO;
import com.yunji.cabinet.vo.CabinetScanVO;
import com.yunji.common.base.BaseBusiness;
import com.yunji.common.constant.HTTPStatus;
import com.yunji.common.constant.LogicCode;
import com.yunji.common.constant.PrefixConstant;
import com.yunji.common.enums.business.StorageType;
import com.yunji.common.enums.common.ErrorEnum;
import com.yunji.common.event.notice.CaptureProductNoticeEvent;
import com.yunji.common.event.notice.StockWarmNoticeEvent;
import com.yunji.common.exception.ServiceException;
import com.yunji.common.model.cache.CabinetCacheDTO;
import com.yunji.common.model.cache.ProductBelongCacheDTO;
import com.yunji.common.model.cache.ProductCacheDTO;
import com.yunji.common.model.domain.SiteDO;
import com.yunji.common.model.domain.StaffDO;
import com.yunji.common.model.dto.LoginInfo;
import com.yunji.common.utils.DecimalUtils;
import com.yunji.common.utils.TimeUtils;
import com.yunji.common.utils.bean.BeanUtils;
import com.yunji.product.bo.ProductAgentSelectQueryBO;
import com.yunji.product.domain.ProductAgentDO;
import com.yunji.product.service.IProductAgentService;
import com.yunji.storage.bo.StockSelectQueryBO;
import com.yunji.storage.business.StockBusiness;
import com.yunji.storage.business.StorageInteractBusiness;
import com.yunji.storage.domain.StockDO;
import com.yunji.storage.dto.StockDTO;
import com.yunji.storage.dto.StorageOperateDTO;
import com.yunji.storage.enums.StorageBusinessType;
import com.yunji.storage.service.IStockService;
import com.yunji.system.context.SystemContext;
import com.yunji.system.service.TokenService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;


/**
 * @version 1.0
 * @Project: yunji-coffee
 * @Package com.yunji.cabinet.business
 * @FileName CabinetOperateBusiness.java
 * @Copyright Copyright © 2024 云集互联. All Rights Reserved
 * Company		com
 * @CreateTime 2024-06-07 10:47:18
 * @Description 货柜操作
 * @Modification Author                    History Time			Version				Description
 * --------------------------------------------------------------------------------
 * HuaAo0803@163.com	2024-06-07 10:47:18		1.0					1.0 Version
 * @since JDK 1.8.0_202
 */
@Component
public class CabinetOperateBusiness extends BaseBusiness {
    @Resource
    AgentService agentService;

    @Resource
    StaffService staffService;

    @Resource
    SiteService siteService;

    @Resource
    ICabinetSiteService cabinetSiteService;

    @Resource
    ICabinetService cabinetService;

    @Resource
    ICabinetCellService cabinetCellService;

    @Resource
    StorageInteractBusiness interactBusiness;

    @Resource
    CabinetTemplateBusiness templateBusiness;

    @Resource
    StockBusiness stockBusiness;

    @Resource
    CabinetBusiness cabinetBusiness;

    @Resource
    ICabinetCellService cellService;

    @Resource
    CabinetConsumer cabinetConsumer;

    @Resource
    MaintainService maintainService;

    @Resource
    ITakeDeliveryService takeDeliveryService;

    @Resource
    ITakeDeliveryInfoService takeDeliveryInfoService;

    @Resource
    FillCargoInfoService fillCargoInfoService;

    @Resource
    IProductAgentService productAgentService;

    @Resource
    IStockService stockService;

    @Resource
    TokenService tokenService;

    @Resource
    DeviceService deviceService;

    private static final String SUPPLY_MESSAGE = "{}商品,已补货完成,本次补货数量{}";

    private static final String ADD_PRODUCT = "BH8888";

    /**
     * @param qrcode 二维码信息
     * @return CabinetVO 货柜详情
     * @Title selectCabinet
     * @Intro 获取货柜详情
     * @Date 2024-06-10 20:24:09.350
     */
    public CabinetScanVO selectCabinet(String qrcode) {
        ContainerDO cabinet = handleContainer(qrcode);
        Long cabinetId = cabinet.getContainerId();
        Long belongId = cabinet.getBelongId();
        logs.info("【员工操作】货柜ID:{},货柜所属ID:{}", cabinetId, belongId);
        CabinetScanVO vo = new CabinetScanVO();
        BeanUtils.clone(cabinet, vo);
//        List<CabinetCellBO> boList = cabinetConsumer.getProductListById(cabinetId, belongId);
        ContainerPriceBO bo = CabinetCache.getCabinetPrice(cabinet.getChipImei());
        List<CabinetCellVO> voList = CabinetConvert.BOToVO(bo);
        vo.setVolt(cabinet.getBattleLevel());
        vo.setSiteId(cabinet.getSiteId());
        vo.setSiteName(BaseCache.getSiteName(cabinet.getSiteId()));
        vo.setLocationName(BaseCache.getSiteLocationName(vo.getLocationId()));
        vo.setTypeCode(cabinet.getTypeCode());
        vo.setTypeName(CabinetCache.getTypeName(cabinet.getTypeCode()));
        vo.setCoulomb(cabinet.getBattleLevel() + "%");
        vo.setCells(voList);
        vo.setLocationAddress(BaseCache.getSiteLocation(vo.getLocationId()).getAddress());
        return vo;
    }

    /**
     * @param cabinet 货柜信息
     * @Title bindCabinet
     * @Intro 绑定员工货柜信息
     * @Date 2024-06-11 00:04:52.768
     */
    @Transactional
    public void bindCabinet(CabinetBindDTO cabinet) {
        LoginInfo user = tokenService.getUser();
        logs.info("【货柜绑定】取出的员工信息{}", user);
        Assert.isTrue(BeanUtils.isNotNull(user), "请先登录");
        CabinetBO cabinetBO = cabinetService.select(CabinetSelectQueryBo.builder().qrcode(cabinet.getQrcode()).build());
        Assert.isTrue(BeanUtils.isNotNull(cabinetBO), ErrorEnum.BUSINESS_712001.getText());
        ContainerDO origin = cabinetBO.getCabinet();

        Long belongId = user.getBelongId();
        logs.info("【货柜绑定】员工所属:{}", belongId);
        BelongDO belong = BaseCache.getBelong(belongId);
        Assert.isTrue(BeanUtils.isNotNull(belong), "所属信息未找到");

        Long siteId = belong.getSiteId();
        Long agentId = belong.getAgentId();
        logs.info("【货柜绑定】网点ID:{},代理ID:{}", siteId, agentId);
        SiteDO site = siteService.getById(siteId);
        Assert.isTrue(BeanUtils.isNotNull(site), "网点信息未找到");

        AgentDTO agent = agentService.select(agentId);
        Integer limit = agent.getContainerLimit();
        logs.info("【货柜绑定】代理货柜数量限制:{}", limit);

        int count = cabinetService.countCabinet(CabinetCountBO.builder().agentId(agentId).build());
        logs.info("【货柜绑定】当前代理货柜数量:{}", count);
        Assert.isTrue((count < limit), ErrorEnum.BUSINESS_312002.getText());

        Long cabinetId = origin.getContainerId();
        logs.info("【货柜绑定】货柜ID：{}", cabinetId);

        // 处理网点信息 防止重复绑定
        CabinetSiteListQueryBO bo = new CabinetSiteListQueryBO();
        bo.setSiteId(siteId);
        bo.setContainerId(cabinetId);
        List<CabinetSiteDO> cabinetSiteList = cabinetSiteService.search(bo);
        Assert.isTrue(BeanUtils.isNull(cabinetSiteList), "货柜网点已经存在绑定");

        ContainerDO update = new ContainerDO();

        update.setContainerId(cabinetId);
        update.setContainerName(cabinet.getContainerName());
        update.setChipSn(origin.getChipSn());
        update.setChipImei(origin.getChipImei());

        update.setTypeCode(cabinet.getTypeCode());
        update.setTemplateId(cabinet.getTemplateId());

        update.setUseStatus(0);
        update.setUseTime(TimeUtils.getTime());

        update.setBelongId(belongId);

        update.setSiteId(siteId);
        update.setLocationId(cabinet.getLocationId());

        update.setStaffId(user.getUserId());
        update.setBindTime(TimeUtils.getNowDate());

        update.setAgentId(agentId);

        // 获取模板信息
        CabinetTemplateBO template = templateBusiness.selectTemplateById(cabinet.getTemplateId());
        logs.info("【绑定货柜】货柜模板:{}", template);
        Assert.isTrue(BeanUtils.isNotNull(template), "没有该模板");

        // 防止遗留货柜格子
        cellService.deleteByContainerIds(cabinetId);
        List<CabinetTemplateCellDO> cells = template.getCellList();
        cells.forEach(c -> {
            Long productId = c.getProductId();
            Assert.isTrue(BeanUtils.isNotNull(productId), ErrorEnum.BUSINESS_512007.getText());

            ProductAgentDO productAgent = productAgentService.select(ProductAgentSelectQueryBO.builder()
                    .productId(productId).status(LogicCode.NO).belongId(belongId).build());
            Assert.isTrue(BeanUtils.isNotNull(productAgent), ErrorEnum.BUSINESS_512006.getText());

            ContainerCell cell = new ContainerCell();
            cell.setProductId(productId);
            cell.setOrdinal(c.getOrdinal());
            cell.setContainerId(cabinetId);
            CapacityCeilingBO ceilingBO = new CapacityCeilingBO();
            ceilingBO.setTypeCode(origin.getTypeCode());
            ceilingBO.setProductId(productId);
            cell.setCeilingQuantity(CabinetCalculate.getCapacityCeiling(ceilingBO).intValue());
            cell.setStatusUpdateTime(TimeUtils.getNowDate());
            cellService.create(cell);
        });

        CabinetSiteDO cabinetSite = new CabinetSiteDO();
        cabinetSite.setSiteId(siteId);
        cabinetSite.setContainerId(cabinetId);
        Assert.isTrue(cabinetSiteService.create(cabinetSite), "修改失败");
        Assert.isTrue(cabinetService.update(update), "修改失败");
    }


    /**
     * @param qrcode   二维码信息
     * @param ordinals 货柜格子信息
     * @Title openedCabinet
     * @Intro 打开货柜格子
     * @Date 2024-06-10 20:33:41.823
     */
    @Transactional
    public String openedCabinet(String qrcode, String ordinals) {
        LoginInfo user = SystemContext.getUser();
        String imei = cabinetService.getImeiByQrcode(qrcode);
        ContainerPriceBO bo = CabinetCache.getCabinetPrice(imei);
        CabinetCacheDTO cabinet = bo.getContainer();
        CabinetValidate.checkCabinetBind(cabinet.getAgentId());
        CabinetValidate.checkStaffAuth(cabinet.getSiteId(), user.getSiteId());
        // 修改占用库存
        // 处理补货信息 先查看是否有补货数据
        MaintainDO maintainDO = new MaintainDO();
        List<ContainerCellPriceBO> priceList = new ArrayList<>();
        for (ContainerCellPriceBO priceBO : bo.getCellPriceList()) {
            ContainerCell cell = priceBO.getCell();
            maintainDO.setStartNums(cell.getProductQuantity());
            priceList.add(priceBO);
        }
//        lockStock(cabinet, priceList);
        maintainDO.setStaffId(user.getUserId());
        maintainDO.setStaffName(user.getRealName());
        maintainDO.setStaffTel(user.getPhone());
        maintainDO.setMaintainCode(CabinetDataCodeGenerate.generateDateCode(PrefixConstant.CABINET_MAINTAIN));
        maintainDO.setLocationId(cabinet.getLocationId());
        MaintainDO select = new MaintainDO();
        select.setContainerId(cabinet.getContainerId());
        select.setStaffId(user.getUserId());
        select.setMaintainStatus(MaintainStatus.UNCOMPLETED.getCode());
        select.setMaintainType(MaintainType.FILL_CARGO.getCode());
        MaintainDO maintain = maintainService.select(select);
        if (BeanUtils.isNotNull(maintain)) {
            maintainDO.setMaintainId(maintain.getMaintainId());
            maintainDO.setStartTime(TimeUtils.getNowDate());
            maintainService.update(maintainDO);
        } else {
            maintainDO.setContainerId(cabinet.getContainerId());
            maintainDO.setChipImei(cabinet.getChipImei());
            maintainDO.setContainerName(cabinet.getContainerName());
            maintainDO.setMaintainType(MaintainType.FILL_CARGO.getCode());
            maintainDO.setTypeCode(CabinetCache.getTypeCode(imei));
            maintainDO.setStartTime(TimeUtils.getNowDate());
            Assert.isTrue(maintainService.create(maintainDO), "新增失败");
        }

        DeviceEventDTO eventDTO = new DeviceEventDTO(maintainDO.getMaintainCode(), maintainDO.getMaintainId(), null,
                new DeviceCommandDTO(DeviceEventEnum.STAFF_RESTOCK.name(), DeviceCommandEnum.OPEN_RESTOCK.name(), cabinet.getChipImei()));

        if (cabinet.getTypeCode().equals(ContainerTypeEnum.COFFEE.getTypeCode())){
            DeviceCommandEngine.addEvent(eventDTO);
        }else {
            DeviceCommandEngine.executeEvent(eventDTO);
        }

        return maintainDO.getMaintainCode();
    }

    /**
     * @return String 处理结果
     * @Title closedCabinet
     * @Intro 关闭货柜格子
     * @Date 2024-06-10 21:40:47.498
     */
    @Transactional
    public String closedCabinet(CabinetCargoDTO dto) {
        String qrcode = dto.getQrcode();
        String imei = cabinetService.getImeiByQrcode(qrcode);
        ContainerPriceBO bo = CabinetCache.getCabinetPrice(imei);
        CabinetCacheDTO cabinet = bo.getContainer();
        MaintainDO select = new MaintainDO();
        select.setContainerId(cabinet.getContainerId());
        select.setMaintainStatus(MaintainStatus.UNCOMPLETED.getCode());
        select.setMaintainType(MaintainType.FILL_CARGO.getCode());
        MaintainDO maintain = maintainService.select(select);
        Assert.isTrue(BeanUtils.isNotNull(maintain), "请先点击开始补货");
        maintain.setChangeVolt(dto.getChangeVolt());
        maintain.setMaintainStatus(MaintainStatus.COMPLETED.getCode());
        maintain.setEndTime(TimeUtils.getNowDate());
        Integer allNums = 0;
        Map<Integer,Integer> map = new HashMap<>();
        for (CabinetCargoInfoDTO infoDTO : dto.getDtoList()) {
            if (infoDTO.getCargoNums() != 0) {
                Integer actualNums = cabinetBusiness.updateCabinetCell(infoDTO.getCargoNums(), infoDTO.getOrdinal(), cabinet.getContainerId(), 0);
                allNums += actualNums;
                Integer ordinal = infoDTO.getOrdinal();
                map.put(ordinal,actualNums);
            }
        }
        GuavaEventBus.post(new CaptureProductNoticeEvent(SystemContext.getUser(), cabinet.getContainerId(), allNums));
        handleStock(cabinet, dto.getDtoList());
        maintain.setCargoNums(allNums);
        maintain.setCloseNums(maintain.getStartNums() + allNums);
        Assert.isTrue(maintainService.update(maintain), "修改失败");
        List<FillCargoInfoDO> infoList = new ArrayList<>();
        for (ContainerCellPriceBO priceBO : bo.getCellPriceList()) {
            FillCargoInfoDO info = new FillCargoInfoDO();
            ContainerCell cell = priceBO.getCell();
            if (map.containsKey(cell.getOrdinal())) {
                BeanUtils.clone(cell, info);
                ProductCacheDTO productDTO = priceBO.getProductBelong().getProductDTO();
                info.setMaintainId(maintain.getMaintainId());
                info.setMaintainCode(maintain.getMaintainCode());
                info.setProductName(productDTO.getProductName());
                info.setAlbumPics(productDTO.getAlbumPics());
                info.setPrice(productDTO.getPrice());
                info.setDiscountPrice(priceBO.getProductBelong().getProductAgentDTO().getDiscountPrice());
                info.setCargoNums(map.get(cell.getOrdinal()));
                infoList.add(info);
            }
        }
        for (FillCargoInfoDO fillCargoInfo : infoList) {
            Assert.isTrue(fillCargoInfoService.create(fillCargoInfo), "新增失败");
        }
        StaffDO response = staffService.select(SystemContext.getUserId());
        StaffDO update = new StaffDO();
        update.setId(SystemContext.getUserId());
        update.setFillCargoCount(response.getFillCargoCount() + 1);
        Assert.isTrue(staffService.update(update), "更新失败");
        return "关闭成功";
    }

    /**
     * 查看货柜
     */
    public CabinetScanVO viewContainer(String qrcode) {
        // 获取员工信息
        LoginInfo user = SystemContext.getUser();

        ContainerDO cabinet = cabinetService.getByQrcode(qrcode);
        ServiceException.throwException(cabinet.getAgentId() == null, HTTPStatus.PAYMENT_REQUIRED, "当前货柜未绑定");
        Long cabinetManagerId = cabinet.getSiteId();

        Integer accreditStatus = Objects.equals(user.getSiteId(), cabinetManagerId) ? AccreditStatus.HAVE_ACCREDIT.getCode() : AccreditStatus.NOT_ACCREDIT.getCode();
        logs.info("【查看货柜】网点绑定状态：{}", accreditStatus);

        CabinetScanVO vo = new CabinetScanVO();
        vo.setContainerId(cabinet.getContainerId());
        vo.setContainerName(cabinet.getContainerName());
        vo.setChipImei(cabinet.getChipImei());
        vo.setOnlineStatus(cabinet.getOnlineStatus());
        vo.setOnlineTime(cabinet.getOnlineTime());
        vo.setOfflineTime(cabinet.getOfflineTime());
        vo.setBattleStatus(cabinet.getBattleStatus());
        vo.setUpdateBattleTime(cabinet.getUpdateBattleTime());
        vo.setAccreditStatus(accreditStatus);
        vo.setQrCode(cabinet.getQrcode());
        vo.setSiteId(cabinetManagerId);
        vo.setSiteName(BaseCache.getSiteName(cabinetManagerId));
        vo.setLocationName(BaseCache.getSiteLocationName(cabinet.getLocationId()));
        vo.setCoulomb(cabinet.getBattleLevel() + "%");
        vo.setTypeCode(cabinet.getTypeCode());
        vo.setLocationAddress(BaseCache.getSiteLocation(cabinet.getLocationId()).getAddress());
        ContainerPriceBO bo = CabinetCache.getCabinetPrice(cabinet.getChipImei());
        vo.setCells(CabinetConvert.BOToVO(bo));
        //有权限展示商品信息
        if (Objects.equals(accreditStatus, AccreditStatus.HAVE_ACCREDIT.getCode())) {
            this.fillCabinetVO(vo, cabinet);
        }
        return vo;
    }


    /**
     * 查看货柜详情
     *
     * @param param
     */
    public CabinetScanVO viewContainerInfo(CabinetDTO param) {
        Long cabinetId = param.getContainerId();
        logs.info("【查看详情】货柜ID:{}", cabinetId);
        CabinetBO bo = cabinetService.select(cabinetId);
        ContainerDO cabinet = bo.getCabinet();
        Assert.isTrue(BeanUtils.isNotNull(cabinet), "未找到货柜信息");

        CabinetScanVO vo = new CabinetScanVO();
        vo.setContainerId(cabinet.getContainerId());
        vo.setContainerName(cabinet.getContainerName());
        vo.setBattleStatus(cabinet.getBattleStatus());
        vo.setUpdateBattleTime(cabinet.getUpdateBattleTime());
        vo.setChipImei(cabinet.getChipImei());
        vo.setOnlineStatus(cabinet.getOnlineStatus());
        vo.setOnlineTime(cabinet.getOnlineTime());
        vo.setOfflineTime(cabinet.getOfflineTime());
        vo.setTypeCode(cabinet.getTypeCode());
        vo.setQrCode(cabinet.getQrcode());
        vo.setSiteId(cabinet.getSiteId());
        vo.setSiteName(BaseCache.getSiteName(cabinet.getSiteId()));
        vo.setLocationName(BaseCache.getSiteLocationName(cabinet.getLocationId()));
        vo.setLocationAddress(BaseCache.getSiteLocation(cabinet.getLocationId()).getAddress());
        this.fillCabinetVO(vo, cabinet);
        return vo;
    }

    /**
     * @param update 更新信息
     * @Title update
     * @Desc 员工操作修改货柜
     * @Date 2024-09-02 12:05:57.130
     */
    public void update(ContainerDO update) {
        // 获取员工信息
        LoginInfo user = SystemContext.getUser();

        Long cabinetId = update.getContainerId();
        logs.info("【查看货柜】货柜ID:{}", cabinetId);
        CabinetBO bo = cabinetService.select(cabinetId);
        ContainerDO cabinet = bo.getCabinet();
        logs.info("【查看货柜】货柜信息：{}", cabinet);
        Assert.isTrue(BeanUtils.isNotNull(cabinet), "未找到货柜信息");

        Long staffManagerId = user.getSiteId();
        Long cabinetManagerId = cabinet.getSiteId();
        logs.info("【查看货柜】员工经理用户ID：{},货柜经理用户ID：{}", staffManagerId, cabinetManagerId);

        Assert.isTrue(Objects.equals(staffManagerId, cabinetManagerId), "无权操作");

        cabinetService.update(update);
    }

    public void takeOneProduct(Long containerId, Integer ordinal) {
        String imei = cabinetService.getImeiById(containerId);
        ContainerPriceBO bo = CabinetCache.getCabinetPrice(imei);
        CabinetCacheDTO cabinet = bo.getContainer();
        Assert.isTrue(DeviceCommandEngine.online(imei), ErrorEnum.BUSINESS_712002.getText());
        List<ContainerCellPriceBO> priceBO = new ArrayList<>();
        for (ContainerCellPriceBO cellPriceBO : bo.getCellPriceList()) {
            if (cellPriceBO.getCell().getOrdinal().equals(ordinal))
                priceBO.add(cellPriceBO);
        }
        handleTakeProduct(cabinet, priceBO);
    }

    /**
     * @Title takeOutProduct
     * @Desc 取出全部货柜商品
     * @Date 2024-10-22 19:37:00.139
     */
    @Transactional
    public void takeAllProduct(Long containerId) {
        String imei = cabinetService.getImeiById(containerId);
        ContainerPriceBO bo = CabinetCache.getCabinetPrice(imei);
        CabinetCacheDTO cabinet = bo.getContainer();
//        Assert.isTrue(DeviceCommandEngine.online(imei), ErrorEnum.BUSINESS_712002.getText());
        handleTakeProduct(cabinet, bo.getCellPriceList());
    }

    private void handleTakeProduct(CabinetCacheDTO cabinet, List<ContainerCellPriceBO> priceBOList) {
        List<CabinetCellUpdateBO> updateCells = new ArrayList<>();
        LoginInfo user = SystemContext.getUser();
        Integer takeNums = 0;
        List<TakeDeliveryInfoDO> infoList = new ArrayList<>();

        // 先改数据库后发指令  指令无法回滚
        for (ContainerCellPriceBO priceBO : priceBOList) {
            ContainerCell cell = priceBO.getCell();
            ProductBelongCacheDTO product = priceBO.getProductBelong();

            TakeDeliveryInfoDO infoDO = new TakeDeliveryInfoDO();;
            infoDO.setProductId(product.getProductDTO().getId());
            infoDO.setProductName(product.getProductDTO().getProductName());
            infoDO.setProductSku(product.getProductDTO().getSku());
            infoDO.setAlbumPics(product.getProductDTO().getAlbumPics());
            infoDO.setPrice(product.getProductDTO().getPrice());
            infoDO.setDiscountPrice(product.getProductDTO().getDiscountPrice());
            infoDO.setTakeNums(cell.getProductQuantity());
            infoDO.setOrdinal(cell.getOrdinal());
            takeNums+=cell.getProductQuantity();
            infoList.add(infoDO);

            CabinetCellUpdateBO cellBO = new CabinetCellUpdateBO();
            cellBO.setCellId(cell.getCellId());
            cellBO.setProductId(cell.getProductId());
            cellBO.setStatus(CellStatus.UNABLE.getCode());
            cellBO.setStatusUpdateTime(TimeUtils.getNowDate());
            cellBO.setLackStatus(LackStatus.YES.getCode());
            cellBO.setLackTime(TimeUtils.getNowDate());
            cellBO.setProductQuantity(0);
            updateCells.add(cellBO);

        }
        TakeDeliveryDO takeDeliveryDO = new TakeDeliveryDO();
        takeDeliveryDO.setContainerId(cabinet.getContainerId());
        takeDeliveryDO.setContainerName(cabinet.getContainerName());
        takeDeliveryDO.setChipImei(cabinet.getChipImei());
        takeDeliveryDO.setStaffId(user.getUserId());
        takeDeliveryDO.setStaffTel(user.getPhone());
        takeDeliveryDO.setStaffName(user.getRealName());
        takeDeliveryDO.setTakeNums(takeNums);
        takeDeliveryDO.setStartTime(TimeUtils.getNowDate());
        takeDeliveryDO.setTakeStatus(LogicCode.YES);
        takeDeliveryDO.setLocationId(cabinet.getLocationId());
        takeDeliveryDO.setTakeCode(CabinetDataCodeGenerate.generateDateCode(PrefixConstant.CABINET_TAKE_DELIVERY));
        takeDeliveryService.create(takeDeliveryDO);

        DeviceEventDTO eventDTO = new DeviceEventDTO(takeDeliveryDO.getTakeCode(), takeDeliveryDO.getTakeId(), null,
                new DeviceCommandDTO(DeviceEventEnum.STAFF_TAKE.name(), DeviceCommandEnum.OPEN_RESTOCK.name(), cabinet.getChipImei()));
        if (cabinet.getTypeCode().equals(ContainerTypeEnum.COFFEE.getTypeCode())){
            DeviceCommandEngine.addEvent(eventDTO);
        }else {
            DeviceCommandEngine.executeEvent(eventDTO);
        }

        for (TakeDeliveryInfoDO infoDO : infoList) {
            infoDO.setTakeId(takeDeliveryDO.getTakeId());
            infoDO.setTakeCode(takeDeliveryDO.getTakeCode());
            takeDeliveryInfoService.create(infoDO);
        }

        // 修改货柜格子状态
        for (CabinetCellUpdateBO updateCell : updateCells) {
            if (BeanUtils.isNotNull(updateCell.getCellId())) {
                cabinetCellService.update(updateCell);
            }
        }
        // 解除占用库存
        unlockStock(cabinet, priceBOList);
    }

    /**
     * @param qrcode 二维码信息
     * @return Cabinet 货柜信息
     * @Title handleQRCode
     * @Intro 处理二维码信息
     * @Date 2024-06-10 21:56:04.860
     */
    private ContainerDO handleContainer(String qrcode) {
        ContainerDO cabinet = cabinetService.getByQrcode(qrcode);
        CabinetValidate.checkCabinetBind(cabinet.getAgentId());
        String chip = cabinet.getChipImei();
        logs.info("【员工操作】货柜芯片信息:{}", chip);
//        Assert.isTrue(DeviceCommandEngine.online(chip), ErrorEnum.BUSINESS_712002.getText());
        LoginInfo user = SystemContext.getUser();
        Assert.isTrue(BeanUtils.isNotNull(user), "请先登录");
        // 判断员工是否能打开对应的货柜
        if (!cabinet.getSiteId().equals(user.getSiteId())) {
            throw new ServiceException(HTTPStatus.FORBIDDEN, "您没有权限打开此柜子");
        }
        return cabinet;
    }


    /**
     * 补充货柜信息
     *
     * @param vo
     * @param cabinet
     */
    public void fillCabinetVO(CabinetScanVO vo, ContainerDO cabinet) {
        Long cabinetId = cabinet.getContainerId();
        Long belongId = cabinet.getBelongId();
        logs.info("【货柜详情】货柜ID:{},所属ID:{}", cabinetId, belongId);
//        List<CabinetCellVO> voList = CabinetConvert.BOToVO(boList);
        ContainerPriceBO bo = CabinetCache.getCabinetPrice(cabinet.getChipImei());
        List<CabinetCellVO> voList = CabinetConvert.BOToVO(bo);
        logs.info("【查看货柜】货柜格子信息：{}", voList);

        Integer emptyQuantity = new Integer(0);
        Integer productQuantity = new Integer(0);
        Integer ceilingQuantity = new Integer(0);

        for (CabinetCellVO cell : voList) {
            emptyQuantity = emptyQuantity + (cell.getCeilingQuantity() - cell.getProductQuantity());
            productQuantity += cell.getProductQuantity();
            ceilingQuantity += cell.getCeilingQuantity();
        }
        vo.setCoulomb(cabinet.getBattleLevel() + "%");
        vo.setCells(voList);
        vo.setEmptyQuantity(emptyQuantity);
        vo.setProductQuantity(productQuantity);
        vo.setCeilingQuantity(ceilingQuantity);
    }


    /**
     * @Title handleStock
     * @Desc 员工补货 商品补货入库
     * @Date 2024-09-14 16:05:56.097
     */
    private void handleStock(CabinetCacheDTO cabinet, List<CabinetCargoInfoDTO> infoDTOList) {
        Integer stockStatus = cabinetConsumer.getStockStatus(cabinet.getBelongId());
        if (Objects.equals(LogicCode.YES, stockStatus)) {
            Integer businessType = StorageBusinessType.OPERATE_BUSINESS.getCode();
            logs.info("【补货入库】业务类型:{}", businessType);
            //库存操作参数
            StorageOperateDTO operateDTO = new StorageOperateDTO();
            List<StockDTO> dtoList = new ArrayList<>();
            Long intoBelongId = cabinet.getBelongId();
            logs.info("【补货入库】入库单位:{}", intoBelongId);
            operateDTO.setBelongId(intoBelongId);
            operateDTO.setStorageType(StorageType.INTO_STORAGE.getCode());
            operateDTO.setBusinessType(businessType);
            operateDTO.setBusinessCode(ADD_PRODUCT);
            for (CabinetCargoInfoDTO dto : infoDTOList) {
                StockDTO stockDTO = new StockDTO();
                stockDTO.setProductId(dto.getProductId());
                stockDTO.setActualQuantity(BigDecimal.valueOf(dto.getCargoNums()));
                dtoList.add(stockDTO);
            }
            operateDTO.setList(dtoList);
            interactBusiness.operateStorage(operateDTO);
            for (CabinetCargoInfoDTO dto : infoDTOList) {
                Long productId = dto.getProductId();
                StockDO stock = stockService.select(new StockSelectQueryBO(cabinet.getBelongId(), productId));
                BigDecimal warmValue = stock.getWarmValue();
                BigDecimal usableStock = stock.getUsableStock();
                logs.info("【预警消息】预警值:{},可用库存:{}", warmValue, usableStock);
                if (DecimalUtils.more(warmValue, usableStock)) {
                    LoginInfo loginInfo = SystemContext.getUser();
                    loginInfo.setBelongId(cabinet.getBelongId());
                    GuavaEventBus.post(new StockWarmNoticeEvent(loginInfo, productId));
                }
            }
        }
    }

    /**
     * @param cabinet
     * @param
     * @Title updateStock
     * @Desc 添加占用库存
     * @Date 2024-09-24 17:13:56.881
     */
//    private void lockStock(CabinetCacheDTO cabinet, List<ContainerCellPriceBO> priceList ) {
//        Integer stockStatus = cabinetConsumer.getStockStatus(cabinet.getBelongId());
//        String chip = cabinet.getChipImei();
//
//        if (Objects.equals(LogicCode.YES, stockStatus)) {
//            String stockKey = OPERATE_STOCK + chip;
//            StringBuilder productIds = new StringBuilder();
//
//            for (ContainerCellPriceBO cellPrice : priceList) {
//                Integer cellStatus = cellPrice.getCell().getStatus();
//                Long productId = cellPrice.getCell().getProductId();
//
//                // 货柜格子为无货 才会增加库存
//                if (Objects.equals(LogicCode.NO, cellStatus)) {
//                    String stockProduct = productId + ",";
//                    productIds.append(stockProduct);
//                }
//            }
//
//            redisCache.set(stockKey, productIds);
//        }
//    }

    /**
     * @param cabinet 货柜
     * @Title unlockStock
     * @Desc 解除占用库存
     * @Date 2024-10-23 11:08:23.014
     */
    private void unlockStock(CabinetCacheDTO cabinet, List<ContainerCellPriceBO> cells) {
        Integer stockStatus = cabinetConsumer.getStockStatus(cabinet.getBelongId());
        if (Objects.equals(LogicCode.YES, stockStatus)) {

            List<StockDO> stockList = new ArrayList<>();

            logs.info("【员工补货】货柜Id:{},补货格子:{}", cabinet.getContainerId(), cells);
            for (ContainerCellPriceBO cell : cells) {
                BigDecimal allNums = BigDecimal.valueOf(cell.getCell().getProductQuantity());
                StockDO stock = new StockDO();
                stock.setBelongId(cabinet.getBelongId());
                stock.setProductId(cell.getCell().getProductId());
                stock.setFrozenStock(allNums.negate());
                stock.setUsableStock(allNums);
                stock.setDisableStock(BigDecimal.ZERO);
                stock.setAllStock(BigDecimal.ZERO);
                stockList.add(stock);
            }

            cabinetConsumer.handleStock(stockList);

        }
    }

    public void unbindCabinet(String qrcode) {
        CabinetBO bo = cabinetService.select(CabinetSelectQueryBo.builder().qrcode(qrcode).build());
        Assert.isTrue(BeanUtils.isNotNull(bo), ErrorEnum.BUSINESS_712001.getText());
        cabinetBusiness.unbindCabinet(bo.getCabinet().getContainerId());
    }

}